OS期末复习

Hello, OS world

编译, 链接

  • strace -f查看进程和他的子进程的所有系统调用
  • gcc -o hello hello.c
    • 子进程1: 编译器compiler写入a.s汇编代码
    • 子进程2: 汇编器assembler写入a.o(ELF…)
    • 子进程3: 链接器linker写入a.out(ELF…)
  • readelf: hello中有什么

终端与shell

  • I/O设备模型: 设备是三种操作的集合:
    • 发送命令、读取状态、传输数据
  • 设备驱动: os中负责与设备交互的程序. 根据设备类型不同, 给每一类设备以统一的接口访问, 实现这个接口的就是设备驱动程序.
  • shell用read从0号文件描述符读入, 按下回车read返回
  • ./hello如何被执行

    • fork-execve
    • execve保留绝大部分进程状态,如文件描述符, 管道和重定向是改变文件描述符
    • sudo echo hello > /etc/a没用的原因: 在execve之前open就已经失败了,还没有sudo
  • hello的第一条指令在哪里?

    • ld.so的_start()
  • hello的main函数执行之前, 系统中发生了什么?

    • 加载器的$_$start, $_$init, 之后调用hello的 $_$start, $__$libc$_$start$_$main…

    callgraph

    • gdb: starti
      • 发现在加载器的$_$start()(这是动态链接, 对于静态链接就是在程序里)
    • info inferiors + pmap
      • 有hello, ld-xxx.so
      • 没有看到libc代码
    • b $_$start() + 再次pmap
      • 有了libc(加载器做的mmap)
    • 最后到main()
    • constructor函数: 可以在main之前执行
    • printf可能会被优化为puts
  • printf()代码位置

    • 动态链接细节不考, 如got plt
  • printf()是线程安全的吗?如何实现线程安全的printf?

    • 并发编程题目: 条件变量, 信号量
    • 复习生产者消费者问题
  • printf字符串末尾没有换行:

    • printf有libc的缓冲区
      • setbuf(); fork的神坑(连缓冲区一起复制fork+printf两次, 6 or 8)
      • 到文件:总是缓冲; 到中断: 换行
    • ltrace有printf
  • printf背后的系统调用: write

  • write写到哪: 文件描述符对应的文件, 例如一个设备/dev/ttyx, 或者是文件系统中的一个文件

  • 文件系统如何实现 FAT, ext2(inode)

  • 如何保护数据不受损坏:

    • 把不可靠的磁盘变可靠: RAID; 奇偶校验允许一块盘坏; 校验位均匀分布在各个盘上
    • 实现崩溃一致性: fsck, 日志